package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.constants.message.HotArticleConstants;
import com.heima.feigns.ArticleFeign;
import com.heima.model.mess.app.NewBehaviorDTO.BehaviorType;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustException;
import com.heima.feigns.AdminFeign;
import com.heima.feigns.ApAuthorFeign;
import com.heima.feigns.ApUserFeign;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.common.dtos.CommentDTO;
import com.heima.model.common.dtos.CommentLikeDTO;
import com.heima.model.common.dtos.CommentSaveDTO;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.pojos.ApComment;
import com.heima.model.common.pojos.ApCommentLike;
import com.heima.model.common.vo.ApCommentVo;
import com.heima.model.mess.app.NewBehaviorDTO;
import com.heima.model.search.vos.SearchArticleVO;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ApUserFeign apUserFeign;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private ApAuthorFeign apAuthorFeign;
    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private CommentHotService commentHotService;
    @Autowired
    RedissonClient redisson;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    //保存评论
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        //获取登录用户id
        Integer userId = AppThreadLocalUtils.getUser().getId();
        //非空判断
        if (userId == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        String newContent = null;
        try {
            //使用阿里云内容审核
            newContent = scanContent(dto.getContent());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //调用远程服务,查询当前登录用户信息
        ResponseResult<ApUser> userResp = apUserFeign.findUserById(userId);
        //非空判断
        if (userResp.getCode() != 0 || userResp.getData() == null) {
            CustException.cust(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST, "当前用户不存在!");
        }
        //获取用户信息
        ApUser user = userResp.getData();
        //调用远程服务,根据文章id查询article
        ResponseResult articleResp = articleFeign.findArticlebb(dto.getArticleId());
        //非空判断
        if (articleResp.getCode() != 0 || articleResp.getData() == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "该文章不存在,无法评论!");
        }
        ApArticle apArticle = (ApArticle) articleResp.getData();

//        ApArticle apArticle = (ApArticle) articleResp.getData();
        //创建评论信息
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setArticleId(dto.getArticleId());
        apComment.setType((short) 0);
//        apComment.setChannelId(apArticle.getChannelId());
        apComment.setContent(newContent);
        apComment.setImage(apArticle.getImages());
        apComment.setLikes(0);
        apComment.setFlag((short) 0);
        apComment.setOrd(0);
        apComment.setReply(0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        //保存到mongo
        mongoTemplate.save(apComment);
        //创建NewBehaviorDTO
        NewBehaviorDTO newBehaviorDTO = new NewBehaviorDTO();
        newBehaviorDTO.setType(BehaviorType.COMMENT);
        newBehaviorDTO.setArticleId(dto.getArticleId());
        newBehaviorDTO.setAdd(1);
        //发送给MQ
        rabbitTemplate.convertAndSend(HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE, JSON.toJSONString(newBehaviorDTO));
        //响应调用者
        return ResponseResult.okResult();
    }

    //保存点赞
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        System.err.println("开始保存点赞!");
        //获取登录用户
        Integer userId = AppThreadLocalUtils.getUser().getId();
        //非空判断
        if (userId == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        //使用redision加锁
        RLock lock = redisson.getLock("likes-lock");
        lock.lock();
        HashMap<String, Object> likesMap;
        try {
            //根据评论id查询评论数据
            Query commentQuery = Query.query(Criteria.where("_id").is(dto.getCommentId()));
            ApComment apComment = mongoTemplate.findOne(commentQuery, ApComment.class);
            //非空判断
            if (apComment == null) {
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "该评论不存在,无法点赞!");
            }
            //根据用户id和评论id查询数据库获取点赞数据
            Query likeQuery = Query.query(Criteria.where("authorId").is(userId).and("commentId").is(dto.getCommentId()));
            ApCommentLike apCommentLike = mongoTemplate.findOne(likeQuery, ApCommentLike.class);
            //创建Map集合保存点赞数
            likesMap = new HashMap<>();
            //判断操作类型
            if (dto.getOperation() == (short) 0) {
                //点赞,判断对应的点赞数据是否存在
                if (apCommentLike != null) {
                    //已经点过赞,无需再次点赞
                    likesMap.put("likes", apComment.getLikes());
                    //创建响应对象并赋值
                    ResponseResult<Object> responseResult = new ResponseResult<>();
                    responseResult.setData(likesMap);
                    responseResult.setErrorMessage("您已经点过赞,无需再次点赞!");
                    responseResult.setCode(200);
                    //响应调用者
                    return responseResult;
                } else {
                    //没有点过赞  创建点赞对象
                    apCommentLike = new ApCommentLike();
                    apCommentLike.setAuthorId(userId);
                    apCommentLike.setCommentId(dto.getCommentId());
                    apCommentLike.setOperation(dto.getOperation());
                    //插入数据库
                    mongoTemplate.save(apCommentLike);
                    //对应的评论,点赞数+1
                    int newLikes = apComment.getLikes() + 1;
                    Update update = new Update();
                    update.set("likes", newLikes);
                    mongoTemplate.updateFirst(commentQuery, update, ApComment.class);
                    //判断修改后的评论,点赞数量是否超过10
                    if (newLikes >= 10) {
                        //满足热点评论的点赞数量条件,调用热点评论方法进行判断
                        commentHotService.hotCommentExecutor(apComment);
                    }
                    //响应前端
                    likesMap.put("likes", newLikes);
                    return ResponseResult.okResult(likesMap);
                }
            } else {
                //取消点赞,判断是否已经点赞
                if (apCommentLike == null) {
                    //没有点过赞,无需取消
                    likesMap.put("likes", apComment.getLikes());
                    //创建响应对象并赋值
                    ResponseResult<Object> responseResult = new ResponseResult<>();
                    responseResult.setData(likesMap);
                    responseResult.setErrorMessage("您还没有点赞,无需取消!");
                    responseResult.setCode(200);
                    //响应调用者
                    return responseResult;
                }
                //点过赞,现在删除
                mongoTemplate.remove(apCommentLike);
                //评论点赞数-1
                Update update = new Update();
                int newLikes = apComment.getLikes() - 1;
                if (apComment.getLikes() > 0) {
                    update.set("likes", newLikes);
                    mongoTemplate.updateFirst(commentQuery, update, ApComment.class);
                    likesMap.put("likes", newLikes);
                }
            }
        } finally {
            lock.unlock();
        }
        //响应调用者
        return ResponseResult.okResult(likesMap);
    }

    //根据文章id分页查询评论列表
    @Override
    public ResponseResult findByArticleId(CommentDTO dto) {
        //判断参数
        if (dto.getMinDate() == null) {
            dto.setMinDate(new Date());
        }
        if (dto.getSize() == null || dto.getSize() == 0) {
            dto.setSize(10);
        }
        Query commentsListQuery = null;
        List<ApComment> hotApComments = null;
        //判断是否是首页
        if (dto.getIndex() == 1) {
            //查询热点评论
            Query hotCommentQuery = Query.query(Criteria.where("flag").is((short) 1).and("articleId").is(dto.getArticleId()));
            Sort hotLikesSort = Sort.by(Sort.Direction.DESC, "likes");
            hotCommentQuery.with(hotLikesSort);
            hotApComments = mongoTemplate.find(hotCommentQuery, ApComment.class);
            //是首页,查询最新的(size-热评数量)条数据,不查询flag=1的热点评论
            commentsListQuery = Query.query(Criteria.where("articleId")
                    .is(dto.getArticleId()).and("flag").ne((short) 1).and("createdTime").lt(new Date()));
        } else {
            //不是首页,根据文章id分页查询,并按照创建时间倒序
            commentsListQuery = Query.query(Criteria.where("articleId")
                    .is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()));
        }
        //创建分页请求对象
        PageRequest pageable = null;
        if (hotApComments != null && hotApComments.size() != 0) {
            pageable = PageRequest.of(0, dto.getSize() - hotApComments.size());
        } else {
            pageable = PageRequest.of(0, dto.getSize());
        }
        commentsListQuery.with(pageable);  //分页
        //创建排序对象
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        commentsListQuery.with(sort);  //排序
        //查询
        List<ApComment> apComments = mongoTemplate.find(commentsListQuery, ApComment.class);
        //判断是否登陆
        ApUser user = AppThreadLocalUtils.getUser();
        //非空判断
        if (user == null || user.getId() == null) {
            //未登录,直接返回评论列表
            hotApComments.addAll(apComments);
            return ResponseResult.okResult(hotApComments);
        }
        //登录了,根据评论id和用户id查询评论点赞表
        //获取所有文章id集合
        List<String> commentIdsList = apComments.stream().map(ApComment::getId).collect(Collectors.toList());
        //设置查询条件
        Query likesQuery = Query.query(Criteria.where("commentId").in(commentIdsList).and("authorId").is(user.getId()));
        //根据当前用户和所有评论评论id查询点赞记录表
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(likesQuery, ApCommentLike.class);
        //非空判断
        if (apCommentLikes.size() == 0) {
            //登录用户没有点赞过显示的任何评论,直接返回评论列表
            hotApComments = new ArrayList<>();
            hotApComments.addAll(apComments);
            return ResponseResult.okResult(hotApComments);
        }
        //遍历评论集合和用户点赞评论表的评论id集合进行筛选
        //创建集合保存新的评论列表
        ArrayList<ApComment> apCommentList = new ArrayList<>();
        ApCommentVo apCommentVo = null;
        for (ApComment apComment : apComments) {  //原有评论集合
            boolean flag = true;
            for (ApCommentLike apCommentLike : apCommentLikes) {  //用户评论点赞集合
                if (apComment.getId().equals(apCommentLike.getCommentId())) {
                    apCommentVo = new ApCommentVo();
                    BeanUtils.copyProperties(apComment, apCommentVo);
                    apCommentVo.setOperation((short) 0);
                    flag = false;
                }
            }
            if (flag) {
                apCommentList.add(apComment);
            } else {
                apCommentList.add(apCommentVo);
            }
        }
        if (hotApComments != null) {
            hotApComments.addAll(apCommentList);
        } else {
            hotApComments = apCommentList;
        }

        return ResponseResult.okResult(hotApComments);
    }

    //内容审核方法
    private String scanContent(String content) throws Exception {
        //校验评论内容是否违规
        Map map = greenTextScan.greenTextScan(content);
        //判断
        String suggestion = (String) map.get("suggestion");
        if (suggestion.equals("block")) {
            //文本中有违规内容,修改
            String filteredContent = (String) map.get("filteredContent");
            return filteredContent;
        }
        if (suggestion.equals("review")) {
            //文本中有不确定内容,转为人工审核
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "评论中有不确定内容,转人工审核!");
        }
        return content;
    }
}